package com.cw.aspect;

import com.cw.annotation.OperationLogAnno;
import com.cw.common.constant.Constants;
import com.cw.entity.ListeningLog;
import com.cw.service.IListeningLogService;
import com.cw.util.EncodeUtils;
import com.cw.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 插入数据的切面日志
 * @author: xnd
 * @date: 2023/11/21 00:01
 **/

@Slf4j
@Aspect
@Configuration
public class OperationAspect {

    @Autowired
    private IListeningLogService listeningLogService;

    //设置切点
    @Pointcut("@annotation(com.cw.annotation.OperationLogAnno)")
    private void pointCut() {
    }

    @Before("pointCut()")
    @Transactional(rollbackFor = Exception.class)
    public void before(JoinPoint joinPoint) throws Throwable {
        ListeningLog listeningLog = new ListeningLog();
        try {
            //获得工号
            String userName = HttpUtil.getRequestHeaderInfo(Constants.USER_NAME);
            //        String userName = "admin";
            //        String realName = "admin";
            //获得姓名
            String realName = null;
            realName = HttpUtil.getRequestHeaderInfo(Constants.REAL_NAME);
            realName = EncodeUtils.urlDecode(realName);
            // 获取方法名
            String methodName = joinPoint.getSignature().getName();
            // 反射获取目标类
            Class<?> targetClass = joinPoint.getTarget().getClass();
            // 获取传入目标方法的参数，返回一个数组
            Object[] args = joinPoint.getArgs();
            // 拿到方法对应的参数类型
            Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
            // 根据类、方法、参数类型（重载）获取到方法的具体信息
            Method objMethod = targetClass.getMethod(methodName, parameterTypes);
            // 获取方法上声明的注解
            OperationLogAnno anno = objMethod.getDeclaredAnnotation(OperationLogAnno.class);
            //操作入口
            listeningLog.setSite(anno.site());
            //执行操作
            listeningLog.setOperation(anno.operation());
            //IP
            listeningLog.setIp(getIpAddr());
            //备注
            listeningLog.setBz(anno.bz());
            //操作者工号
            listeningLog.setCreateBy(userName);
            //操作者姓名
            listeningLog.setRealName(realName);
            //操作时间
            listeningLog.setCreateTime(LocalDateTime.now());
            //接口方法
            listeningLog.setMethod(methodName);
            //类型
            listeningLog.setType(anno.type());
            //传入参数
            listeningLog.setArgs(Arrays.toString(args));
            //调用接口保存日志
            listeningLogService.save(listeningLog);
        } catch (Exception e) {
            //错误日志保存要记录 下次加上
            log.info("日志插入失败------------------------------------------");
        }
    }

    /**
     * 获取IP地址
     */
    private String getIpAddr() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
}
